package com.uobgroup.ews.uam.core.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.uobgroup.ews.uam.core.dao.ReferenceDao;
import com.uobgroup.ews.uam.core.dao.ReferenceTypeDao;
import com.uobgroup.ews.uam.core.domain.Reference;
import com.uobgroup.ews.uam.core.domain.ReferenceType;
import com.uobgroup.ews.uam.core.enums.ScopeType;
import com.uobgroup.ews.uam.core.model.ReferenceResult;
import com.uobgroup.ews.uam.core.model.ReferenceResultList;
import com.uobgroup.ews.uam.core.model.ReferenceResultParamsName;
import com.uobgroup.ews.uam.core.model.StringType;
import com.uobgroup.ews.uam.core.model.ReferenceTypeResult;
import com.uobgroup.ews.uam.core.model.ReferenceTypeResultList;

/**
 * @author phuongtran
 * 
 */

@Service
@Transactional
public class PickListsServiceImpl implements PickListsService {

   @Autowired
   private ReferenceDao referenceDao;

   @Autowired
   private ReferenceTypeDao referenceTypeDao;

   /*
    * (non-Javadoc)
    * 
    * @see
    * com.uobgroup.ews.uam.core.service.PickListsService#getReferenceTypeResultList
    * ()
    */
   @Override
   public ReferenceTypeResultList getReferenceTypeResultList() {
      List<ReferenceType> lstAppScope = referenceTypeDao.findReferenceTypesByScope(ScopeType.APPLICATION);
      List<ReferenceType> lstSecScope = referenceTypeDao.findReferenceTypesByScope(ScopeType.SECURITY);
      List<ReferenceType> lstMerge = new ArrayList<ReferenceType>();
      if (lstAppScope != null && lstAppScope.size() > 0) {
         lstMerge.addAll(lstAppScope);
      }
      if (lstSecScope != null && lstSecScope.size() > 0) {
         lstMerge.addAll(lstSecScope);
      }

      return buildReferenceTypeResultList(lstMerge);
   }

   /*
    * (non-Javadoc)
    * 
    * @see
    * com.uobgroup.ews.uam.core.service.PickListsService#getReferenceResultList
    * (java.util.HashMap)
    */
   @Override
   public ReferenceResultList getReferenceResultList(HashMap<String, String> params) {
      String strId = params.get(ReferenceResultParamsName.REFERENCE_TYPE_ID);
      Long id = getIdNumber(strId);
      if (id != null) {
         ReferenceType refType = referenceTypeDao.findReferenceTypeByIdAndScope(id, ScopeType.APPLICATION);
         if (refType == null) {
            refType = referenceTypeDao.findReferenceTypeByIdAndScope(id, ScopeType.SECURITY);
         }
         if (refType != null) {
            List<Reference> lstRef = referenceDao.findAllReferencesByType(refType);
            if (lstRef != null) {
               ReferenceResultList refResList = buildReferenceResultList(lstRef);
               return refResList;
            }
            else {
               return new ReferenceResultList();
            }
         }
         else {
            return new ReferenceResultList();
         }
      }
      else {
         return new ReferenceResultList();
      }

   }

   private ReferenceTypeResult buildReferenceTypeResult(ReferenceType refType) {
      StringType refStringTypeName = new StringType();
      refStringTypeName.setName("name");
      refStringTypeName.setValue(refType.getName());

      StringType refStringTypeId = new StringType();
      refStringTypeId.setName("id");
      refStringTypeId.setValue(refType.getId().toString());
      
      ReferenceTypeResult refTypeResult = new ReferenceTypeResult();
      refTypeResult.getString().add(refStringTypeName);
      refTypeResult.getString().add(refStringTypeId);

      return refTypeResult;
   }

   private ReferenceTypeResultList buildReferenceTypeResultList(List<ReferenceType> lstRefType) {
      ReferenceTypeResultList refTypeResLst = new ReferenceTypeResultList();
      Iterator<ReferenceType> itRefType = lstRefType.iterator();
      while (itRefType.hasNext()) {
         ReferenceType refType = itRefType.next();
         ReferenceTypeResult refTypeRes = buildReferenceTypeResult(refType);
         refTypeResLst.getEntry().add(refTypeRes);
      }
      return refTypeResLst;
   }

   private ReferenceResult buildReferenceResult(Reference ref) {
      StringType refStringTypeName = new StringType();
      refStringTypeName.setName("name");
      refStringTypeName.setValue(ref.getName());

      StringType refStringTypeCode = new StringType();
      refStringTypeCode.setName("code");
      refStringTypeCode.setValue(ref.getCode());

      ReferenceResult refResult = new ReferenceResult();
      refResult.getString().add(refStringTypeName);
      refResult.getString().add(refStringTypeCode);

      return refResult;
   }

   private ReferenceResultList buildReferenceResultList(List<Reference> lstRef) {
      ReferenceResultList refResList = new ReferenceResultList();

      Iterator<Reference> itRef = lstRef.iterator();
      while (itRef.hasNext()) {
         Reference ref = itRef.next();
         ReferenceResult refRes = buildReferenceResult(ref);
         refResList.getEntry().add(refRes);
      }

      return refResList;
   }

   private Long getIdNumber(String numStr) {
      Long id = null;
      try {
         id = Long.parseLong(numStr);
      }
      catch (Exception e) {
         id = null;
      }
      return id;
   }
}
